package general.guicontrols.layoutmanager;

import general.art.CenteredCluster;
import general.art.Cluster;
import general.art.Node;
import general.guicontrols.clusterpanels.ClusterDisplay;
import general.guicontrols.clusterpanels.NodePanel;

import java.awt.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Map.Entry;


public class ClusterLayout implements LayoutManager {

	private static final int TWO  = 2;

	private Node seedNode;

	private class SimLayout{


		private Map<Node, Point> mapOfNodeToPosition = new HashMap<Node, Point>(); 

		private Random myRandom = new Random();

		public SimLayout(CenteredCluster c){


			seedNode = c.getSeedNode();

			for(Node  n : c.getNodes()){

				if( n != seedNode){
					mapOfNodeToPosition.put(n, new Point( myRandom.nextInt(1000), myRandom.nextInt(1000) ));
				} else {

					mapOfNodeToPosition.put(n, new Point( myRandom.nextInt(500), myRandom.nextInt(500) ));

				}
			}



			for (int count = 0; count < 2 ; count++){

				reCalculatePosition(c);

			}


		}

		private void reCalculatePosition(Cluster c){


			HashMap<Node, Point> newNodeToPos = new HashMap<Node, Point>();	

			for(Node n : mapOfNodeToPosition.keySet()){

				if(n != seedNode){

					double x = 0; //mapOfNodeToPosition.get(n).x;
					double y = 0; //mapOfNodeToPosition.get(n).y;

					for(Node o : mapOfNodeToPosition.keySet()){

						if ( n != o){

							double distance = mapOfNodeToPosition.get(n).distance(   mapOfNodeToPosition.get(o)  ); 
							double forceOfAttraction = 0.25;//Math.pow(distance, TWO);
							double forceOfRepulsion = -600 / distance;

							double vectorX  = mapOfNodeToPosition.get(n).x - 		mapOfNodeToPosition.get(o).x;
							double vectorY  = mapOfNodeToPosition.get(n).y - 		mapOfNodeToPosition.get(o).y;

							if(c.linked(n, o)){						

								//Ask if the reface of attraction is greater that the force of replusion
								//x +=  vec.getX() * forceOfAttraction - vec.getX() * forceOfRepulsion; //+ myRandom.nextInt(3);
								//y +=  vec.getY() * forceOfAttraction - vec.getY() * forceOfRepulsion; //+ myRandom.nextInt(3);

								//*
								x += vectorX * forceOfAttraction;
								y += vectorY * forceOfAttraction;

								//*/
							}

							//Move nodes away from each other
							x += vectorX * forceOfRepulsion;
							y += vectorY * forceOfRepulsion;


						}
					}

					x /= mapOfNodeToPosition.size();
					y /= mapOfNodeToPosition.size();


					x += mapOfNodeToPosition.get(n).x;
					y += mapOfNodeToPosition.get(n).y;

					newNodeToPos.put(n,  new Point( (int)x, (int)y));
				} 
			}


			mapOfNodeToPosition = newNodeToPos;

		}

		public Map<Node, Point> getMap(){

			return mapOfNodeToPosition;

		}


	}



	private final SimLayout layout;

	private final Map<Node, NodePanel> map;

	public ClusterLayout(Map<Node, NodePanel> map, CenteredCluster c){

		this.map = map;
		layout = new SimLayout(c);

	}


	/* Required by LayoutManager. */
	public void addLayoutComponent(String name, Component comp) {}

	/* Required by LayoutManager. */
	public void removeLayoutComponent(Component comp) {}

	/* Required by LayoutManager. */
	public Dimension preferredLayoutSize(Container parent) {

		return new Dimension(1000, 1000);
	}

	/* Required by LayoutManager. */
	public Dimension minimumLayoutSize(Container parent) {
		return new Dimension(1000, 1000);
	}

	/* Required by LayoutManager. 
	/*
	 * This is called when the panel is first displayed,
	 * and every time its size changes.
	 * Note: You CAN'T assume preferredLayoutSize or
	 * minimumLayoutSize will be called -- in the case
	 * of applets, at least, they probably won't be.
	 */
	public void layoutContainer(Container parent) {

		ClusterDisplay p = (ClusterDisplay)parent;
		int xOffSet = p.getXOffSet();
		int yOffSet = p.getXOffSet();
		//System.out.println(seedNode);
		//System.out.println(layout.getMap().size());
		for(Entry<Node, Point> e : layout.getMap().entrySet()){

			Component c = map.get(e.getKey());

			System.out.println(e.getKey());
			c.setBounds(e.getValue().x + xOffSet, e.getValue().y + yOffSet, 100, 100);

			//}

		}

	}

}